package com.asen.commons.core.base.result;

import com.asen.commons.core.base.ResultCode;
import com.asen.commons.core.base.enums.ResultTypeEnum;
import com.asen.commons.exception.*;
import com.asen.commons.utils.EnumUtils;
import com.asen.commons.utils.JsonMapper;

import java.io.Serializable;
import java.util.Map;

public class ApiResult<T> implements Serializable {
    private final long serialVersionUID;
    private String type;
    private String code;
    private String message;
    private String detail;
    private String extCode;
    private String extMessage;
    private Boolean extSuccess;
    private T result;
    private Map<String, Object> extra;

    public ApiResult() {
        this.serialVersionUID = 1L;
    }

    public ApiResult(String type, String code, String message) {
        this.serialVersionUID = 1L;
        this.type = type;
        this.code = code;
        this.message = message;
    }

    public ApiResult(ResultCode resultCode) {
        this.serialVersionUID = 1L;
        this.type = resultCode.getType().getValue();
        this.code = resultCode.getCode();
        this.message = resultCode.getMessage();
    }

    public ApiResult(ResultCode resultCode, String message) {
        this((ResultCode)resultCode, message, (String)null);
    }

    public ApiResult(ResultCode resultCode, String message, String detail) {
        this(resultCode);
        if (message != null) {
            this.message = message;
        }

        if (detail != null) {
            this.detail = detail;
        }

    }

    public static <T> ApiResult<T> data(T object) {
        ApiResult<T> result = new ApiResult(BaseResultCode.C0000);
        result.setResult(object);
        return result;
    }

    public static <T> ApiResult<T> success() {
        return new ApiResult(BaseResultCode.C0000);
    }

    public static <T> ApiResult<T> success(String message) {
        return new ApiResult(BaseResultCode.C0000, message);
    }

    public static <T> ApiResult<T> success(String message, String detail) {
        return new ApiResult(BaseResultCode.C0000, message, detail);
    }

    public static <T> ApiResult<T> fail() {
        return fail(BaseResultCode.E0000);
    }

    public static <T> ApiResult<T> fail(String message) {
        return fail(BaseResultCode.E0000, message);
    }

    public static <T> ApiResult<T> fail(String message, String detail) {
        return fail(BaseResultCode.E0000, message, detail);
    }

    public static <T> ApiResult<T> fail(ResultCode resultCode) {
        return new ApiResult(resultCode);
    }

    public static <T> ApiResult<T> fail(ResultCode resultCode, String message) {
        return new ApiResult(resultCode, message);
    }

    public static <T> ApiResult<T> fail(ResultCode resultCode, String message, String detail) {
        return new ApiResult(resultCode, message, detail);
    }

    public static <T> ApiResult<T> warn(String message) {
        return new ApiResult(BaseResultCode.W0000, message);
    }

    public static <T> ApiResult<T> warn(String message, String detail) {
        return new ApiResult(BaseResultCode.W0000, message, detail);
    }

    public static <T> ApiResult<T> valueOf(Throwable e) {
        return valueOf(e, (ResultCode)null);
    }

    public static <T> ApiResult<T> valueOf(Throwable e, ResultCode defaultErrorCode) {
        ResultTypeEnum errorType = null;
        ResultCode errorCode = null;
        String message = null;
        String detail = null;
        if (e instanceof BaseException) {
            BaseException baseException = (BaseException)e;
            errorCode = baseException.getCode();
            errorType = baseException.getType();
            message = e.getMessage();
            detail = baseException.getDetail();
        }

        if (e instanceof IllegalArgumentException || e instanceof IllegalStateException) {
            message = e.getMessage();
        }

        if (errorCode == null) {
            errorCode = defaultErrorCode;
        }

        if (errorType == null) {
            if (errorCode != null) {
                errorType = errorCode.getType();
            } else {
                errorType = ResultTypeEnum.ERROR;
            }
        }

        if (errorCode == null) {
            if (e instanceof IllegalArgumentException || e instanceof IllegalStateException || e instanceof BeanValidateException || e instanceof ParseException || e instanceof IllegalLogicException) {
                errorCode = BaseResultCode.E0002;
            }

            if (e instanceof TokenInvalidException) {
                errorCode = BaseResultCode.E0003;
            }
        }

        if (errorCode == null) {
            if (EnumUtils.equal(ResultTypeEnum.INFO, errorType)) {
                errorCode = BaseResultCode.C0000;
            } else if (EnumUtils.equal(ResultTypeEnum.WARN, errorType)) {
                errorCode = BaseResultCode.W0000;
            } else {
                errorCode = BaseResultCode.E0000;
            }
        }

        if (e instanceof RemoteException && detail == null) {
            RemoteException exception = (RemoteException)e;
            StringBuilder sb = (new StringBuilder()).append("服务调用失败！\n").append("path=").append(exception.getPath()).append(",status=").append(exception.getStatus()).append(",message=").append(exception.getMessage()).append(",trace=").append(e.getCause());
            detail = sb.toString();
        }

        ApiResult<T> apiResult = new ApiResult(errorCode, message);
        apiResult.setType(errorType.getValue());
        apiResult.setDetail(detail);
        return apiResult;
    }

    public boolean isSuccess() {
        return "C0000".equals(this.code);
    }

    public String getType() {
        return this.type;
    }

    public String getCode() {
        return this.code;
    }

    public String getMessage() {
        return this.message;
    }

    public String getDetail() {
        return this.detail;
    }

    public void setDetail(String detail) {
        this.detail = detail;
    }

    public T getResult() {
        return this.result;
    }

    public void setType(String type) {
        this.type = type;
    }

    public void setCode(String code) {
        this.code = code;
    }

    public void setMessage(String message) {
        this.message = message;
    }

    public void setResult(T result) {
        this.result = result;
    }

    public String getExtCode() {
        return this.extCode;
    }

    public void setExtCode(String extCode) {
        this.extCode = extCode;
    }

    public String getExtMessage() {
        return this.extMessage;
    }

    public void setExtMessage(String extMessage) {
        this.extMessage = extMessage;
    }

    public Map<String, Object> getExtra() {
        return this.extra;
    }

    public void setExtra(Map<String, Object> extra) {
        this.extra = extra;
    }

    public Boolean isExtSuccess() {
        return this.extSuccess;
    }

    public void setExtSuccess(Boolean extSuccess) {
        this.extSuccess = extSuccess;
    }

    //public static void main(String[] args) {
    //    IllegalLogicException illegalLogicException = new IllegalLogicException("帐号密码错误！");
    //    System.out.println(JsonMapper.obj2json(valueOf(illegalLogicException)));
    //}
}
